const fetch = require('node-fetch');
const retry = require('bluebird-retry');
const retryPromise = require('bluebird');
const Web3 = require('web3');
const config = require('./config');
const apiUrl = 'https://metamon-api.radiocaca.com/usm-api';

function MetamonApi(address, chain, privateKey) {
    let self = this;
    self.address = address;
    self.accessToken = "";

    self.web3 = new Web3(chain.rpc);
    if (!privateKey.startsWith('0x')) {
        privateKey = '0x' + privateKey;
    }
    let account = self.web3.eth.accounts.privateKeyToAccount(privateKey);
    self.web3.eth.accounts.wallet.add(account);
    self.web3.eth.defaultAccount = account.address;
}

MetamonApi.prototype.setAccessToken = function(accessToken) {
    let self = this;
    self.accessToken = accessToken;
}

MetamonApi.prototype.post = function(path, paramters) {
    
    let self = this;
    let url = apiUrl + '/' + path;
    let headers = {};
    if (self.accessToken.length > 0) {
        headers = {"accesstoken":self.accessToken};
    }
    
    return self.retryRequest(() => {
        return new Promise((resolve, reject) => {
            try {
                fetch(url, {
                method: 'post',
                body: paramters,
                headers: headers,
                }).then((response) => {
                    response.json().then((result) => { 
                        resolve(result);
                    }).catch(err => {
                        reject(err);
                    });
                }).catch(err => {
                    reject(err);
                });
                
            } catch (err) {
                reject(err);
            }
        });
    });
    
}

/// 登录获取accessToken
MetamonApi.prototype.login = async function() {
    let self = this;
    let owner = self.web3.eth.defaultAccount;
    let msg = "LogIn";
    let sign = await self.web3.eth.sign(msg, owner);
    
    const paramters = new URLSearchParams();
    paramters.append('address', self.address);
    paramters.append('sign', sign);
    paramters.append('msg', msg);
    paramters.append('network', 1);
    paramters.append('clientType', 'MetaMask');
    let result = await self.post('login', paramters);

    return result.data.accessToken;
}

/// 获取元兽岛元兽列表
MetamonApi.prototype.getMetamonList = async function () {
    let self = this;
    const paramters = new URLSearchParams();
    paramters.append('address', self.address);
    paramters.append('page', 1);
    paramters.append('pageSize', 5000);
    let result = await self.post('getWalletPropertyList', paramters);
    return result.data.metamonList;
}

/// 获取元兽王国元兽列表
MetamonApi.prototype.getKingdomMonsterList = async function () {
    let self = this;
    const paramters = new URLSearchParams();
    paramters.append('address', self.address);
    paramters.append('orderType', 2);
    paramters.append('position', 2);
    let result = await self.post('kingdom/monsterList', paramters);
    return result.data;
}

/// 获取元兽详情
MetamonApi.prototype.getMetamonInfo = async function (metamonId) {
    let self = this;

    const paramters = new URLSearchParams();
    paramters.append('address', self.address);
    paramters.append('metamonId', metamonId);
    let result = await self.post('getMetamonProperties', paramters);
    return result.data;
}

/// 是否支付
MetamonApi.prototype.isPay = async function (monsterA, monsterB, battleLevel) {
    let self = this;
    const paramters = new URLSearchParams();
    paramters.append('monsterA', monsterA);
    paramters.append('monsterB', monsterB);
    paramters.append('battleLevel', battleLevel);
    paramters.append('address', self.address);
    let result = await self.post('startPay', paramters);
    let data = result.data;
    return data.pay;
}

/// 攻击
MetamonApi.prototype.battle = async function (monsterA, monsterB, battleLevel) {
    let self = this;
    const paramters = new URLSearchParams();
    paramters.append('monsterA', monsterA);
    paramters.append('monsterB', monsterB);
    paramters.append('battleLevel', battleLevel);
    paramters.append('address', self.address);
    let result = await self.post('startBattle', paramters);
    let data = result.data;
    return data;
}

/// 获取可攻击的对象
MetamonApi.prototype.getBattleObjects = async function (monsterId, front) {
    let self = this;
    const paramters = new URLSearchParams();
    paramters.append('address', self.address);
    paramters.append('metamonId', monsterId);
    paramters.append('front', front);
    let result = await self.post('getBattelObjects', paramters);
    let data = result.data;
    return data.objects;
}

/// 开蛋
MetamonApi.prototype.openEgg = async function () {
    let self = this;
    const paramters = new URLSearchParams();
    paramters.append('address', self.address);
    let result = await self.post('openMonsterEgg', paramters);
    return result;
}

/// 合成蛋
MetamonApi.prototype.mintEgg = async function () {
    let self = this;
    const paramters = new URLSearchParams();
    paramters.append('address', self.address);
    let result = await self.post('composeMonsterEgg', paramters);
    return result;
}

/// 查询背包
MetamonApi.prototype.checkBag = async function () {
    let self = this;
    const paramters = new URLSearchParams();
    paramters.append('address', self.address);
    let result = await self.post('checkBag', paramters);
    let data = result.data;
    return data.item;
}

/// 元兽升级
MetamonApi.prototype.upgrade = async function (nftId) {
    let self = this;
    const paramters = new URLSearchParams();
    paramters.append('address', self.address);
    paramters.append('nftId', nftId);
    let result = await self.post('updateMonster', paramters);
    return result;
}

/// 元兽属性升级
MetamonApi.prototype.addAttr = async function (nftId, attrType) {
    let self = this;
    const paramters = new URLSearchParams();
    paramters.append('address', self.address);
    paramters.append('nftId', nftId);
    paramters.append('attrType', attrType);
    let result = await self.post('addAttr', paramters);
    return result;
}

/// 元兽增加经验
MetamonApi.prototype.addExp = async function (nftId) {
    let self = this;
    const paramters = new URLSearchParams();
    paramters.append('address', self.address);
    paramters.append('nftId', nftId);
    let result = await self.post('expUpMonster', paramters);
    return result;
}

/// 元兽是否能批量升级
MetamonApi.prototype.batchUpgradeStatus = async function () {
    let self = this;
    const paramters = new URLSearchParams();
    paramters.append('address', self.address);
    let result = await self.post('batch-upgrade/status', paramters);
    return result;
}

/// 元兽批量升级所需物品
MetamonApi.prototype.batchUpgradePay = async function () {
    let self = this;
    const paramters = new URLSearchParams();
    paramters.append('address', self.address);
    let result = await self.post('batch-upgrade/pay', paramters);
    return result;
}
/// 元兽批量升级
MetamonApi.prototype.batchUpgradeOperate = async function () {
    let self = this;
    const paramters = new URLSearchParams();
    paramters.append('address', self.address);
    let result = await self.post('batch-upgrade/operate', paramters);
    return result;
}

MetamonApi.prototype.retryRequest = async function (request) {
    let self = this;
    return new Promise((resolve, reject) => {
        /// 重试3次
        retry(() => {
            return request();
        }, { max_tries: 5, interval: 3000 }).then(function (result) {
            resolve(result);
        }).catch(function (error) {
            reject(error);
        });
    });

}

module.exports = MetamonApi;